{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-11-30T02:15:59.006048Z",
     "start_time": "2018-11-30T02:15:58.226498Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'spVal': 0.48813, 'right': -0.04465028571428572, 'left': 1.0180967672413792, 'spInd': 0}\n",
      "{'spVal': 0.39435, 'right': {'spVal': 0.197834, 'right': -0.023838155555555553, 'left': 1.0289583666666666, 'spInd': 1}, 'left': {'spVal': 0.582002, 'right': 1.980035071428571, 'left': {'spVal': 0.797583, 'right': 2.9836209534883724, 'left': 3.9871632, 'spInd': 1}, 'spInd': 1}, 'spInd': 1}\n"
     ]
    }
   ],
   "source": [
    "from numpy import *\n",
    "\n",
    "#加载数据集\n",
    "def loadData(filename):\n",
    "    dataMat = []\n",
    "    fr = open(filename)\n",
    "    for line in fr.readlines():\n",
    "        line = line.strip().split('\\t')\n",
    "        for i in range(len(line)):\n",
    "            line[i] = float(line[i])\n",
    "        dataMat.append(line)\n",
    "    return dataMat\n",
    "\n",
    "#切分数据集，对于特征属性feature，以value作为中点，小于value作为数据集1，大于value作为数据集2\n",
    "def binSplitData(data, feature, value):\n",
    "    #nonzero，当使用布尔数组直接作为下标对象或者元组下标对象中有布尔数组时，\n",
    "    #都相当于用nonzero()将布尔数组转换成一组整数数组，然后使用整数数组进行下标运算。\n",
    "    mat1 = data[nonzero(data[:,feature] > value)[0],:]\n",
    "    mat2 = data[nonzero(data[:,feature] <= value)[0],:]\n",
    "    return mat1, mat2\n",
    "\n",
    "#找到数据切分的最佳位置，遍历所有特征及其可能取值找到使误差最小化的切分阈值\n",
    "#生成叶子节点,即计算属于该叶子的所有数据的label的均值（回归树使用总方差）\n",
    "def regLeaf(data):\n",
    "    return mean(data[:,-1])\n",
    "\n",
    "#误差计算函数：总方差\n",
    "def regErr(data):\n",
    "    return var(data[:,-1]) * shape(data)[0]\n",
    "\n",
    "#最佳切分查找函数\n",
    "def chooseBestSplit(data, leafType=regLeaf, errType=regErr, ops=(1,4)):\n",
    "    #容许的误差下降值\n",
    "    tolS = ops[0]\n",
    "    #切分的最少样本数\n",
    "    tolN = ops[1]\n",
    "    #如果数据的y值都相等，即属于一个label，则说明已经不用再分了，则返回叶子节点并退出\n",
    "    if len(set(data[:,-1].T.tolist()[0])) == 1:\n",
    "        return None, leafType(data)\n",
    "    #否则，继续分\n",
    "    m,n = shape(data)\n",
    "    #原数据集的误差\n",
    "    s = regErr(data)\n",
    "    #最佳误差(先设为极大值),最佳误差对应的特征的index，和对应的使用的切分值\n",
    "    best_s =  inf\n",
    "    best_index = 0\n",
    "    best_val = 0\n",
    "    for feat_index in range(n-1):\n",
    "        for val in set(data[:,feat_index].T.A.tolist()[0]):\n",
    "            #根据特征feat_index和其对应的划分取值val将数据集分开\n",
    "            mat1, mat2 = binSplitData(data, feat_index, val)\n",
    "            #若某一个数据集大小小于tolN，则停止该轮循环\n",
    "            if (shape(mat1)[0] < tolN) or (shape(mat2)[0] < tolN):\n",
    "                continue\n",
    "            new_s = errType(mat1) + errType(mat2)\n",
    "            if new_s < best_s:\n",
    "                best_s = new_s\n",
    "                best_index = feat_index\n",
    "                best_val = val\n",
    "    #如果最佳的误差相较于总误差下降的不多，则停止分支，返回叶节点\n",
    "    if (s-best_s) < tolS:\n",
    "        return None, leafType(data)\n",
    "    #如果划分出来的两个数据集，存在大小小于tolN的，也停止分支，返回叶节点\n",
    "    mat1, mat2 = binSplitData(data, best_index, best_val)\n",
    "    if (shape(mat1)[0] < tolN) or (shape(mat2)[0] < tolN):\n",
    "        return None, leafType(data)\n",
    "    #否则，继续分支，返回最佳的特征和其选取的值\n",
    "    return best_index, best_val\n",
    "\n",
    "#创建回归树\n",
    "def createTree(data, leafType=regLeaf, errType=regErr, ops = (1,4)):\n",
    "    #找到最佳的划分特征以及其对应的值\n",
    "    feat, val = chooseBestSplit(data, leafType, errType, ops)\n",
    "    #若达到停止条件，feat为None并返回数值（回归树）或线性方程（模型树）\n",
    "    if feat is None:\n",
    "        return val\n",
    "    #若未达到停止条件，则根据feat和对应的val将数据集分开，然后左右孩子递归地创建回归树\n",
    "    #tree 存储了当前根节点划分的特征以及其对应的划分值，另外，左右孩子也作为字典存储\n",
    "    rgtree = {}\n",
    "    rgtree['spInd'] = feat\n",
    "    rgtree['spVal'] = val\n",
    "    lset, rset = binSplitData(data,feat,val)\n",
    "    rgtree['left'] = createTree(lset,leafType, errType, ops)\n",
    "    rgtree['right'] = createTree(rset,leafType, errType, ops)\n",
    "    return rgtree\n",
    "\n",
    "#测试上述函数，分类单特征样本\n",
    "data = mat(loadData('ex00.txt'))\n",
    "rgtree = createTree(data)\n",
    "print(rgtree)\n",
    "#测试上述函数，分类多特征样本\n",
    "data1 = mat(loadData('ex0.txt'))\n",
    "rgtree1 = createTree(data1)\n",
    "print(rgtree1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-11-30T01:32:09.850266Z",
     "start_time": "2018-11-30T01:32:09.838263Z"
    }
   },
   "source": [
    "## 剪枝\n",
    "之前所做的一些关于容许误差下降值tolS和tolN属于一种预剪枝，但是根据数据量级的不同，需要时不时地修改设置的阈值，太繁琐，下面展示一个例子。\n",
    "给定两个数据集‘ex00.txt’和‘ex2.txt’，均为单一特征的样本数据。画出二者的分布图："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-11-30T02:56:12.044767Z",
     "start_time": "2018-11-30T02:56:09.844207Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一棵树：\n",
      " {'spVal': 0.48813, 'right': -0.04465028571428572, 'left': 1.0180967672413792, 'spInd': 0}\n",
      "第二棵树：\n",
      " {'spVal': 0.499171, 'right': {'spVal': 0.457563, 'right': {'spVal': 0.126833, 'right': {'spVal': 0.084661, 'right': {'spVal': 0.044737, 'right': 4.091626, 'left': -2.544392714285715, 'spInd': 0}, 'left': 6.509843285714284, 'spInd': 0}, 'left': {'spVal': 0.373501, 'right': {'spVal': 0.335182, 'right': {'spVal': 0.324274, 'right': {'spVal': 0.297107, 'right': {'spVal': 0.166765, 'right': {'spVal': 0.156067, 'right': -6.247900000000001, 'left': -12.1079725, 'spInd': 0}, 'left': {'spVal': 0.202161, 'right': 3.4496025, 'left': {'spVal': 0.217214, 'right': -11.822278500000001, 'left': {'spVal': 0.228473, 'right': 6.770429, 'left': {'spVal': 0.25807, 'right': -13.070501, 'left': 0.40377471428571476, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': -19.9941552, 'spInd': 0}, 'left': 15.05929075, 'spInd': 0}, 'left': {'spVal': 0.350725, 'right': -22.693879600000002, 'left': -15.08511175, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.437652, 'right': {'spVal': 0.412516, 'right': {'spVal': 0.385021, 'right': 3.6584772500000016, 'left': -0.8923554999999995, 'spInd': 0}, 'left': 14.38417875, 'spInd': 0}, 'left': -12.558604833333334, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.467383, 'right': 3.4331330000000007, 'left': 12.50675925, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.729397, 'right': {'spVal': 0.640515, 'right': {'spVal': 0.613004, 'right': {'spVal': 0.582311, 'right': {'spVal': 0.553797, 'right': {'spVal': 0.51915, 'right': 101.73699325000001, 'left': {'spVal': 0.543843, 'right': 110.979946, 'left': 109.38961049999999, 'spInd': 0}, 'spInd': 0}, 'left': 97.20018024999999, 'spInd': 0}, 'left': 123.2101316, 'spInd': 0}, 'left': 93.67344971428572, 'spInd': 0}, 'left': {'spVal': 0.666452, 'right': 114.1516242857143, 'left': {'spVal': 0.706961, 'right': {'spVal': 0.698472, 'right': 108.92921799999999, 'left': 104.82495374999999, 'spInd': 0}, 'left': 114.554706, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.952833, 'right': {'spVal': 0.759504, 'right': 78.08564325, 'left': {'spVal': 0.790312, 'right': 102.35780185714285, 'left': {'spVal': 0.833026, 'right': {'spVal': 0.811602, 'right': 88.78449880000001, 'left': 81.110152, 'spInd': 0}, 'left': {'spVal': 0.944221, 'right': {'spVal': 0.85497, 'right': 95.27584316666666, 'left': {'spVal': 0.910975, 'right': {'spVal': 0.892999, 'right': {'spVal': 0.872883, 'right': 102.25234449999999, 'left': 95.181793, 'spInd': 0}, 'left': 104.825409, 'spInd': 0}, 'left': 96.452867, 'spInd': 0}, 'spInd': 0}, 'left': 87.3103875, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.958512, 'right': 112.42895575000001, 'left': 105.24862350000001, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}\n"
     ]
    }
   ],
   "source": [
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "data1 = np.array(loadData('ex00.txt'))\n",
    "data2 = np.array(loadData('ex2.txt'))\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(121)\n",
    "ax.scatter(data1[:,0], data1[:,1])\n",
    "ax1 = fig.add_subplot(122)\n",
    "ax1.scatter(data2[:,0], data2[:,1])\n",
    "plt.show()\n",
    "\n",
    "data1 = mat(data1)\n",
    "data2 = mat(data2)\n",
    "print('第一棵树：\\n',createTree(data1))\n",
    "print('第二棵树：\\n',createTree(data2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由上图可知，二者都是可以分成两类，但是当我们用之前的回归树分类时，前者是可以分为两类的，而后者的回归树变得十分复杂（延展出很多分支很深的分支）。这是因为预剪枝中的停止阈值tolS对数量级十分敏感，需要二次修改。这样就浪费了大量的时间。此外，预剪枝很可能造成欠拟合，因此剪枝最长用的是后剪枝。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-11-30T03:46:55.464643Z",
     "start_time": "2018-11-30T03:46:54.487943Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "merging\n",
      "merging\n",
      "merging\n",
      "merging\n",
      "merging\n",
      "merging\n",
      "merging\n",
      "merging\n",
      "merging\n",
      "{'spVal': 0.499171, 'right': {'spVal': 0.457563, 'right': {'spVal': 0.126833, 'right': {'spVal': 0.084661, 'right': {'spVal': 0.044737, 'right': 4.091626, 'left': -2.544392714285715, 'spInd': 0}, 'left': 6.509843285714284, 'spInd': 0}, 'left': {'spVal': 0.373501, 'right': {'spVal': 0.335182, 'right': {'spVal': 0.324274, 'right': {'spVal': 0.297107, 'right': {'spVal': 0.166765, 'right': {'spVal': 0.156067, 'right': -6.247900000000001, 'left': -12.1079725, 'spInd': 0}, 'left': {'spVal': 0.202161, 'right': 3.4496025, 'left': -5.801872785714286, 'spInd': 0}, 'spInd': 0}, 'left': -19.9941552, 'spInd': 0}, 'left': 15.05929075, 'spInd': 0}, 'left': {'spVal': 0.350725, 'right': -22.693879600000002, 'left': -15.08511175, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.437652, 'right': {'spVal': 0.412516, 'right': 1.383060875000001, 'left': 14.38417875, 'spInd': 0}, 'left': -12.558604833333334, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': 7.969946125, 'spInd': 0}, 'left': {'spVal': 0.729397, 'right': {'spVal': 0.640515, 'right': {'spVal': 0.613004, 'right': {'spVal': 0.582311, 'right': 101.580533, 'left': 123.2101316, 'spInd': 0}, 'left': 93.67344971428572, 'spInd': 0}, 'left': {'spVal': 0.666452, 'right': 114.1516242857143, 'left': {'spVal': 0.706961, 'right': 106.87708587499999, 'left': 114.554706, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.952833, 'right': {'spVal': 0.759504, 'right': 78.08564325, 'left': {'spVal': 0.790312, 'right': 102.35780185714285, 'left': {'spVal': 0.833026, 'right': {'spVal': 0.811602, 'right': 88.78449880000001, 'left': 81.110152, 'spInd': 0}, 'left': {'spVal': 0.944221, 'right': {'spVal': 0.85497, 'right': 95.27584316666666, 'left': {'spVal': 0.910975, 'right': {'spVal': 0.892999, 'right': {'spVal': 0.872883, 'right': 102.25234449999999, 'left': 95.181793, 'spInd': 0}, 'left': 104.825409, 'spInd': 0}, 'left': 96.452867, 'spInd': 0}, 'spInd': 0}, 'left': 87.3103875, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'left': {'spVal': 0.958512, 'right': 112.42895575000001, 'left': 105.24862350000001, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}, 'spInd': 0}\n"
     ]
    }
   ],
   "source": [
    "#判断是否为树\n",
    "def isTree(obj):\n",
    "    return (type(obj).__name__ == 'dict')\n",
    "\n",
    "#递归函数，找到叶节点平均值，塌陷处理\n",
    "def getMean(tree):\n",
    "    if isTree(tree['right']):\n",
    "        tree['right'] = getMean(tree['right'])\n",
    "    if isTree(tree['left']):\n",
    "        tree['left'] = getMean(tree['left'])\n",
    "    return (tree[left] + tree[right])/2.0\n",
    "\n",
    "#剪枝\n",
    "def prune(tree, testData):\n",
    "    #如果测试数据为空，则直接对原树进行塌陷处理\n",
    "    if shape(testData)[0] == 0:\n",
    "        return getMean(tree)\n",
    "    #如果当前节点不是叶子节点的父节点，将test数据分支，然后递归地对左子树和右子树剪枝\n",
    "    if isTree(tree['left']) or isTree(tree['right']):\n",
    "        lSet, rSet = binSplitData(testData, tree['spInd'], tree['spVal'])\n",
    "    if isTree(tree['left']):\n",
    "        tree['left'] = prune(tree['left'],lSet)\n",
    "    if isTree(tree['right']):\n",
    "        tree['right'] = prune(tree['right'],rSet)\n",
    "    #如果当前节点是叶子节点的父节点，即左右子树都为一个数值而非子树，计算剪枝前后，测试数据在这个父节点出的误差\n",
    "    #根据误差是否降低来判断是否剪枝（合并左右叶子节点到其父节点，使该父节点成为新的叶子节点）\n",
    "    if (not isTree(tree['left'])) and (not isTree(tree['right'])):\n",
    "        lSet, rSet = binSplitData(testData, tree['spInd'], tree['spVal'])\n",
    "        #不剪枝\n",
    "        errorNoMerge = sum(power(lSet[:,-1]-tree['left'],2)) + sum(power(rSet[:,-1]-tree['right'],2))\n",
    "        #剪枝\n",
    "        treeMean = (tree['left'] + tree['right'])/2.0\n",
    "        errorMerge = sum(power(testData[:,-1]-treeMean,2))\n",
    "        if errorMerge < errorNoMerge:\n",
    "            print('merging')\n",
    "            return treeMean\n",
    "        else:\n",
    "            return tree\n",
    "    else:\n",
    "        return tree\n",
    "    \n",
    "#将上述data2进行剪枝\n",
    "testData = mat(loadData('ex2test.txt'))\n",
    "tree = createTree(data2)\n",
    "new_tree = prune(tree,testData)\n",
    "print(new_tree)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 模型树\n",
    "__普通回归树__：叶子节点为数值，表示属于该分组的样本的y值的平均值；   \n",
    "__模型树__：叶子节点是线性函数，对下述样本点，用两条直线建模要优于用两个值。\n",
    "模型树优点：可解释性，预测准确度高。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-11-30T03:56:28.640470Z",
     "start_time": "2018-11-30T03:56:28.046050Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "data1 = np.array(loadData('exp2.txt'))\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111)\n",
    "ax.scatter(data1[:,0], data1[:,1])\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
